//package com.boot2.core.dao.datasource.xa;
//
//import com.boot2.core.dao.datasource.DynamicDataSource;
//import com.mysql.cj.jdbc.MysqlXADataSource;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.beans.MutablePropertyValues;
//import org.springframework.beans.factory.support.BeanDefinitionRegistry;
//import org.springframework.beans.factory.support.GenericBeanDefinition;
//import org.springframework.boot.context.properties.bind.Bindable;
//import org.springframework.boot.context.properties.bind.Binder;
//import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
//import org.springframework.boot.context.properties.source.ConfigurationPropertyNameAliases;
//import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
//import org.springframework.boot.context.properties.source.MapConfigurationPropertySource;
//import org.springframework.context.EnvironmentAware;
//import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
//import org.springframework.core.env.Environment;
//import org.springframework.core.type.AnnotationMetadata;
//import org.springframework.util.Assert;
//
//import javax.sql.DataSource;
//import javax.sql.XADataSource;
//import java.util.HashMap;
//import java.util.Iterator;
//import java.util.Map;
//import java.util.Set;
//
///**
// * 分布式多数据源注册
// * @author ZHUFEIFEI
// */
//public class XaDynamicDataSourceRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware {
//    private final Logger log = LoggerFactory.getLogger(getClass());
//    private Environment env;
//
//    /**
//     * 配置别名设置
//     */
//    private final static ConfigurationPropertyNameAliases aliases = new ConfigurationPropertyNameAliases();
//
//    static {
//        //其他数据源可能不叫url, 所以设置别名匹配
//        aliases.addAliases("url", new String[]{"jdbc-url"});
//        aliases.addAliases("username", new String[]{"user"});
//    }
//    /**
//     * 获取默认的数据源
//     *
//     * @return
//     */
//    public DataSource getDefaultDataSource() {
//        return getDataSource(customDefaultDatasourceName);
//    }
//
//
//    /**
//     * 构建出来的分布式数据源集合
//     */
//    private Map<String, DataSource> xaDataSources = new HashMap<>();
//    private String customDefaultDatasourceName;
//
//    /**
//     * 根据配置的数据源名称获取数据源
//     *
//     * @param name
//     * @return
//     */
//    public DataSource getDataSource(String name) {
//        Assert.notNull(xaDataSources, "没有配置自定义数据源，不需要获取动态数据源");
//        DataSource dataSource = xaDataSources.get(name);
//        Assert.notNull(dataSource, "配置了数据源名称【" + customDefaultDatasourceName + "】，但是没有找到该数据源，请检查配置");
//        return dataSource;
//    }
//
//    /**
//     * 参数绑定工具 springboot2.0新推出
//     */
//    private Binder binder;
//
//    @Override
//    public void setEnvironment(Environment environment) {
//        this.env = environment;
//        //获取参数绑定器，用于将参数与类属性进行绑定，就是赋值
//        this.binder = Binder.get(environment);
//    }
//
//    @Override
//    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//        customDefaultDatasourceName = env.getProperty("spring.datasource.customDefaultName");
//
//        Map xaProperties = binder.bind("spring.jta.atomikos.datasource", Bindable.of(Map.class)).orElseGet(() -> new HashMap(1));
//        Map<String, Map<String, Object>> dataSourceMap = binder.bind("spring.custom-datasource", Bindable.of(Map.class)).orElseGet(() -> new HashMap<>(1));
//        Set<Map.Entry<String, Map<String, Object>>> entrySet = dataSourceMap.entrySet();
//        Iterator<Map.Entry<String, Map<String, Object>>> iterator = entrySet.iterator();
//        MysqlXADataSource druidXADataSource = null;
//        while (iterator.hasNext()) {
//            Map.Entry<String, Map<String, Object>> entry = iterator.next();
//            druidXADataSource = bindWithClass(MysqlXADataSource.class, entry.getValue());
//            System.out.println("druidXADataSource = " + druidXADataSource);
//            DataSource dataSource = wrap(druidXADataSource, entry.getKey(), xaProperties);
//            xaDataSources.put(entry.getKey(), dataSource);
//            log.info("注册分布式数据源 xaDataSources: " + xaDataSources);
//        }
//        GenericBeanDefinition define = new GenericBeanDefinition();
//        define.setBeanClass(DynamicDataSource.class);
//        define.setPrimary(true);
//        MutablePropertyValues pv = define.getPropertyValues();
//        //DynamicRoutingDataSource类上的属性
//        pv.addPropertyValue("defaultTargetDataSource", getDefaultDataSource());
//        pv.addPropertyValue("targetDataSources", xaDataSources);
//        registry.registerBeanDefinition("dynamicDataSource", define);
//    }
//
//    private DataSource wrap(XADataSource xaDataSource, String name, Map<String, Object> xaProperties) {
//        org.springframework.boot.jta.atomikos.AtomikosDataSourceBean bean = new org.springframework.boot.jta.atomikos.AtomikosDataSourceBean();
//        if (!xaProperties.isEmpty()) {
//            this.bindWithBean(bean, xaProperties);
//        }
//        bean.setUniqueResourceName(name);
//        bean.setXaDataSource(xaDataSource);
//        return bean;
//    }
//
//    private <T> T bindWithClass(Class<T> clazz, Map properties) {
//        ConfigurationPropertySource source = new MapConfigurationPropertySource(properties);
//        Binder binder = new Binder(new ConfigurationPropertySource[]{source.withAliases(aliases)});
//        return binder.bind(ConfigurationPropertyName.EMPTY, Bindable.of(clazz)).get();
//    }
//
//    private <T> T bindWithBean(T bean, Map<String, Object> properties) {
//        ConfigurationPropertySource source = new MapConfigurationPropertySource(properties);
//        Binder binder = new Binder(new ConfigurationPropertySource[]{source.withAliases(aliases)});
//        return binder.bind(ConfigurationPropertyName.EMPTY, Bindable.ofInstance(bean)).get();
//    }
//
//}
